import 'terms.dart';

/// 优先级较高的常用术语
final highPriorityCommonTermsList = [
  Terms.pullStick.desc,
  Terms.digStick.desc,
  Terms.doublePull.desc,
  Terms.stick.desc,
  Terms.connect.desc,
  Terms.stickConnect.desc,
  Terms.connectDiagonalConnect.desc,
  Terms.resist.desc,
  Terms.group.desc,
  Terms.clamp.desc,
  Terms.top.desc,
  // Terms.sharp.desc,
  Terms.crush.desc,
  Terms.turn.desc,
  Terms.crowd.desc,
  Terms.attach.desc,
  Terms.long.desc,
  // Terms.stretch.desc,
  // Terms.shoulderHit.desc,
  Terms.pull.desc,
  Terms.hold.desc,
  Terms.thrustPeep.desc,
  // Terms.dot.desc,
  Terms.stand.desc,
  Terms.depend.desc,
  Terms.thrustTigerThorn.desc,
  Terms.back.desc,
  Terms.dig.desc,
  // Terms.stretchPillar.desc
];

final highPriorityCommonTermsList2 = [
  Terms.crowd.desc,
  Terms.resist.desc,
  Terms.back.desc,
  Terms.long.desc,
];

// 常用术语判定
String judgeCommonTerms(int distanceSquared, int oppositeCount, int selfCount,
    {List<ChessStep>? selfStepList,
    List<ChessStep>? oppositeStepList,
    Board? board,
    ChessStep? chessStep,
    TermsCoordinates? descCoordinates}) {
  String terms = Terms.none.desc;

  // 紧贴术语
  if (distanceSquared == 1) {
    terms = nearTerms(oppositeCount, selfCount,
            oppositeStepList: oppositeStepList,
            board: board,
            chessStep: chessStep,
            descCoordinates: descCoordinates,
            selfStepList: selfStepList)
        .desc;
  }
  // 斜斜术语
  else if (distanceSquared == 2) {
    terms = slopeTerms(oppositeCount, selfCount,
            stepList: oppositeStepList,
            selfStepList: selfStepList,
            board: board,
            chessStep: chessStep,
            descCoordinates: descCoordinates)
        .desc;
  }

  return terms;
}

Terms nearTerms(int count1, int count4,
    {List<ChessStep>? selfStepList,
    List<ChessStep>? oppositeStepList,
    Board? board,
    ChessStep? chessStep,
    TermsCoordinates? descCoordinates}) {
  // printInfo('进入紧贴术语判定s1:$count1,s4:$count4');
  int s1 = count1;
  int s4 = count4;
  bool isSymmetry() {
    if (oppositeStepList == null) {
      return false;
    }
    return oppositeStepList.length >= 2 &&
        (oppositeStepList[0].x == oppositeStepList[1].x ||
            oppositeStepList[0].y == oppositeStepList[1].y);
  }

  if (descCoordinates != null) {
    // printInfo('棋子的线路：${descCoordinates.line}');
    // 特殊点 ⼀⼀ +2S1
    if (isOneOne(descCoordinates)) {
      s1 = s1 + 2;
      // printInfo('修正后的s1:$s1,s4:$s4');
    }
    // ⼀线 +1S1
    else if (isOneLine(descCoordinates)) {
      s1 = s1 + 1;
      // printInfo('修正后的s1:$s1,s4:$s4');
    }
  }

  switch (s4) {
    case 0:
      if (s1 == 2) {
        // 2S1*0S4*1S5 ⼀线：扳 其他：挖
        List s5List = sCount(board!, chessStep!, 2, true);
        if (s5List.length == 1) {
          if (isOneLine(descCoordinates!)) {
            // ChessStep s1Step = oppositeStepList![0];
            ChessStep s5Step = s5List[0];
            bool isSame = oppositeStepList!.any(
                (s1Step) => (s1Step.x == s5Step.x || s1Step.y == s5Step.y));
            if (isSame) {
              var terms = backTerms(2, board);
              if (terms == Terms.pull.desc) {
                return Terms.doublePull;
              } else {
                return Terms.pull;
              }
            } else {
              return Terms.sharpTop;
            }
          } else {
            return Terms.dig;
          }
        }
        // 2S1*0S4
        if (isSymmetry()) {
          return Terms.dig;
        } else {
          if (isOneLine(descCoordinates!)) {
            if (oppositeStepList == null || oppositeStepList.isEmpty) {
              return Terms.none;
            }
            ChessStep coordinate1 = oppositeStepList[0];
            switch (judgeFromAbstractDirection(board, chessStep)) {
              case AbstractDirection.middle:
                return Terms.chess;
              case AbstractDirection.specialSideCornerLeft:
                if (coordinate1.x == chessStep.x) {
                  return Terms.depend;
                } else if (coordinate1.x == chessStep.x + 1) {
                  return Terms.hold;
                }
              case AbstractDirection.specialSideCornerBottom:
                if (coordinate1.y == chessStep.y) {
                  return Terms.depend;
                } else if (coordinate1.y == chessStep.y + 1) {
                  return Terms.hold;
                }
              case AbstractDirection.specialSideCornerRight:
                if (coordinate1.x == chessStep.x) {
                  return Terms.depend;
                } else if (coordinate1.x == chessStep.x - 1) {
                  return Terms.hold;
                }
              case AbstractDirection.specialSideCornerTop:
                if (coordinate1.y == chessStep.y) {
                  return Terms.depend;
                } else if (coordinate1.y == chessStep.y - 1) {
                  return Terms.hold;
                }
              case AbstractDirection.specialDot:
                if (isOneOne(descCoordinates)) {
                  return Terms.dotOneOne;
                }
            }
          } else {
            return Terms.crowd;
          }
        }
      } else if (s1 == 1) {
        if (oppositeStepList!.isNotEmpty) {
          var coordinate1 = oppositeStepList[0];
          if (changedX(chessStep!) == coordinate1.x) {
            if (changedY(chessStep) > coordinate1.y) {
              if (isClamp(board!, chessStep, type: 1)) {
                return Terms.clamp;
              }
            } else {
              if (isClamp(board!, chessStep, type: 0)) {
                return Terms.clamp;
              }
            }
          } else if (changedY(chessStep) == coordinate1.y) {
            if (changedX(chessStep) > coordinate1.x) {
              if (isClamp(board!, chessStep, type: 2)) {
                return Terms.clamp;
              }
            } else {
              if (isClamp(board!, chessStep, type: 3)) {
                return Terms.clamp;
              }
            }
          }
        }
        // 1S1*0S4（碰系列）：进⼊复合术语层
        var term = judgeCompositeTerms(board!, chessStep!,
            selfStepList: selfStepList,
            oppositeStepList: oppositeStepList,
            descCoordinates: descCoordinates,
            distance: 1);
        isHaveJudgeComposite = true;
        if (term.desc != Terms.none.desc) {
          return term;
        } else {
          // 进入后续判定
        }
      }
      break;
    case 1:

      /// 3S1*1S4
      if (s1 == 3) {
        if (isOneOne(descCoordinates!)) {
          return Terms.crowdOneOne;
        } else if (isOneLine(descCoordinates)) {
          return Terms.prevent; // 到底是阻渡还是断开
        } else {
          return Terms.crowd;
        }
      }

      /// 2S1*1S4
      else if (s1 == 2) {
        if (isSymmetry()) {
          return Terms.crush;
        } else {
          if (isOneLine(descCoordinates!)) {
            if (isOneOne(descCoordinates)) {
              return Terms.crowdOneOne;
            } else {
              var coordinate4 = selfStepList!.first;
              if (oppositeStepList!.any((value) =>
                  (value.x == coordinate4.x &&
                      value.x == changedX(chessStep!)) ||
                  (value.y == coordinate4.y &&
                      value.y == changedY(chessStep!)))) {
                return Terms.top;
              } else {
                return Terms.crush;
              }
            }
          } else {
            if (isTwoTwo(descCoordinates)) {
              return Terms.crowdTwoTwo;
            } else if (isThreeThree(descCoordinates)) {
              return Terms.crowdThreeThree;
            } else {
              return Terms.crowd;
            }
          }
        }
      }

      /// 1S1*1S4(贴系列)：进⼊复合术语层
      else if (s1 == 1) {
        if (oppositeStepList!.isNotEmpty) {
          var coordinate1 = oppositeStepList[0];
          if (changedX(chessStep!) == coordinate1.x) {
            if (changedY(chessStep) > coordinate1.y) {
              if (isClamp(board!, chessStep, type: 1)) {
                return Terms.clamp;
              }
            } else {
              if (isClamp(board!, chessStep, type: 0)) {
                return Terms.clamp;
              }
            }
          } else if (changedY(chessStep) == coordinate1.y) {
            if (changedX(chessStep) > coordinate1.x) {
              if (isClamp(board!, chessStep, type: 2)) {
                return Terms.clamp;
              }
            } else {
              if (isClamp(board!, chessStep, type: 3)) {
                return Terms.clamp;
              }
            }
          }
        }
        isHaveJudgeComposite = true;
        return judgeCompositeTerms(board!, chessStep!,
            selfStepList: selfStepList,
            oppositeStepList: oppositeStepList,
            descCoordinates: descCoordinates,
            distance: 1);
      } else if (s1 == 0) {
        int s2 = sCount(board!, chessStep!, 2, false).length;
        if (s2 == 0) {
          var coordinate4 = selfStepList![0];
          // 1S4*0S1
          switch (judgeFromAbstractDirection(board, chessStep)) {
            case AbstractDirection.middle:
              return Terms.stretch;
            case AbstractDirection.specialSideCornerLeft:
            case AbstractDirection.specialSideCornerRight:
              if (changedY(chessStep) == coordinate4.y) {
                return Terms.stretchPillar;
              } else {
                return Terms.stretch;
              }
            case AbstractDirection.specialSideCornerTop:
            case AbstractDirection.specialSideCornerBottom:
              if (changedX(chessStep) == coordinate4.x) {
                return Terms.stretchPillar;
              } else {
                return Terms.stretch;
              }
            case AbstractDirection.specialDot:
              return Terms.stretch;
          }
        }
      }
      break;

    /// 2S4
    case 2:
      // 0S1*2S4/1S1*2S4/2S1*2S4
      if (s1 == 0 || s1 == 1 || s1 == 2) {
        ChessStep? coordinate41;
        ChessStep? coordinate42;
        int x = changedX(chessStep!);
        int y = changedY(chessStep);
        if (selfStepList![0].y == y) {
          coordinate41 = selfStepList[0];
          coordinate42 = selfStepList[1];
        } else {
          coordinate41 = selfStepList[1];
          coordinate42 = selfStepList[0];
        }

        if ((coordinate41.x == x && coordinate42.x == x) ||
            (coordinate41.y == y && coordinate42.y == y)) {
          return Terms.stick;
        }

        if (_haveChess(board!, chessStep, coordinate41, coordinate42)) {
          if (backTerms(2, board).contains(Terms.pull.desc)) {
            return Terms.pullStick;
          } else {
            return Terms.stickConnect;
          }
        } else {
          return Terms.group;
        }
      }
      break;
    case 3:

      /// 0S1*3S4、1S1*3S4
      if (s1 == 0 || s1 == 1) {
        return reJudgeStick(board!);
      }
      break;
    case 4:

      /// 4S4*0S1
      if (s1 == 0) {
        return reJudgeStick(board!);
      }
      break;
  }
  return Terms.none;
}

reJudgeStick(Board board) {
  var lastTerms = backTerms(1, board);
  // printInfo('lastTerms:$lastTerms');
  if (backTerms(2, board).contains(Terms.pull.desc)) {
    return Terms.pullStick;
  } else if (lastTerms.contains(Terms.dig.desc)) {
    return Terms.digStick;
  } else {
    return Terms.stick;
  }
}

/// 可能断的地方是否有子
bool _haveChess(Board board, ChessStep chessStep, ChessStep coordinate41,
    ChessStep coordinate42) {
  // printInfo('断的位置是否有子');

  int chessBw(int x, int y) {
    if (x < 1 || x > 19) {
      return 0;
    }
    if (y < 1 || y > 19) {
      return 0;
    }

    return board.getChessValue(20 - y, x);
  }

  int x = changedX(chessStep);
  int y = changedY(chessStep);

  /// 左下
  if ((coordinate41.y == y && coordinate41.x == x - 1) &&
      (coordinate42.x == x && coordinate42.y == y - 1)) {
    if (chessBw(coordinate42.x - 1, coordinate41.y - 1) == 3 - chessStep.bw) {
      return true;
    }
  }

  /// 右下
  if ((coordinate41.y == y && coordinate41.x == x + 1) &&
      (coordinate42.x == x && coordinate42.y == y - 1)) {
    if (chessBw(coordinate42.x + 1, coordinate41.y - 1) == 3 - chessStep.bw) {
      return true;
    }
  }

  /// 左上
  if ((coordinate41.y == y && coordinate41.x == x - 1) &&
      (coordinate42.x == x && coordinate42.y == y + 1)) {
    if (chessBw(coordinate42.x - 1, coordinate41.y + 1) == 3 - chessStep.bw) {
      return true;
    }
  }

  /// 右上
  if ((coordinate41.y == y && coordinate41.x == x + 1) &&
      (coordinate42.x == x && coordinate42.y == y + 1)) {
    if (chessBw(coordinate42.x + 1, coordinate41.y + 1) == 3 - chessStep.bw) {
      return true;
    }
  }
  return false;
}

/// 斜斜术语判定
Terms slopeTerms(int count2, int count5,
    {List<ChessStep>? stepList,
    List<ChessStep>? selfStepList,
    Board? board,
    ChessStep? chessStep,
    TermsCoordinates? descCoordinates}) {
  bool isSymmetry(List<ChessStep> steps) {
    // for (var it in steps) {
    //   printInfo('${it.x},${it.y}');
    // }
    return steps.length >= 2 &&
        (steps[0].x == steps[1].x || steps[0].y == steps[1].y);
  }

  int s2 = count2;
  int s5 = count5; // 颜色相同

  // printInfo('进入斜斜术语判定s2:$s2,s5:$s5');

  if (descCoordinates != null) {
    // 特殊点 ⼀⼀ +2S1
    if (isOneOne(descCoordinates)) {
      s2 = s2 + 3;
      // printInfo('修正后的s2:$s2,s5:$s5');
    }
    // ⼀线 +1S1
    else if (isOneLine(descCoordinates)) {
      s2 = s2 + 2;
      // printInfo('修正后的s2:$s2,s5:$s5');
    }
  }

  switch (s2) {
    case 0:
      if (s5 == 4) return Terms.chess;
      // if (s5 == 3) return Terms.doubleTiger;
      // 0S2*2S5
      if (s5 == 2) {
        if (!isSymmetry(selfStepList!)) {
          return Terms.connectDiagonalConnect;
        }
      }
      // 0S2*1S5：尖
      if (s5 == 1) return Terms.sharp;
      break;
    case 1:
      // 1S2*3S5
      if (s5 == 3) return Terms.doubleTiger;
      // 1S2*2S5
      if (s5 == 2) {
        return isSymmetry(selfStepList!)
            ? Terms.tiger
            : Terms.connectDiagonalConnect;
      }
      // 1S2*1S5：尖
      if (s5 == 1) return Terms.sharp;
      // 1S2*0S5：肩冲系列,进⼊复合术语判定
      if (s5 == 0) {
        isHaveJudgeComposite = true;
        return judgeCompositeTerms(board!, chessStep!,
            selfStepList: selfStepList,
            oppositeStepList: stepList,
            descCoordinates: descCoordinates);
      }
      break;
    case 2:
      // 2S2*2S5
      if (s5 == 2) {
        if (isOneOne(descCoordinates!)) {
          return Terms.tigerBackTiger;
        } else {
          if (isSymmetry(selfStepList!)) {
            ChessStep step1 = selfStepList.first;
            ChessStep step2 = selfStepList.last;
            printInfo('step1:$step1');
            printInfo('step2:$step2');
            List<ChessStep> nearList1 = getNearChess(board!, step1);
            List<ChessStep> nearList2 = getNearChess(board, step2);
            printInfo('nearList1:$nearList1');
            printInfo('nearList2:$nearList2');
            if (nearList1.any((value) => nearList2.contains(value))) {
              return Terms.resist; // 有问题
            } else {
              return Terms.thrustTigerThorn;
            }
          } else {
            return Terms.connectDiagonalConnect;
          }
        }
      }
      // 2S2*1S5
      else if (s5 == 1) {
        if (isOneLine(descCoordinates!)) {
          return Terms.sharp;
        } else {
          return isSymmetry(stepList!) ? Terms.thrustPeep : Terms.breakWedge;
        }
      }
      // 2S2*0S5
      else if (s5 == 0) {
        if (isOneLine(descCoordinates!)) {
          return Terms.chess;
        } else {
          int s4 = sCount(board!, chessStep!, 1, true).length;
          if (s4 > 0) {
            if (s4 != 1) {
              s2 = 1;
            }
            // 进入复合术语,同时s2=1
            var terms = judgeCompositeTerms(board, chessStep,
                descCoordinates: descCoordinates, ss2: s2);
            return terms;
          }
          if (isSymmetry(stepList!)) {
            return Terms.thrust;
          } else {
            var terms = Terms.thrust;
            // 穿象眼,存入常用术语盒子
            if (boxTerms1.contains(terms.desc)) {
              // return '${Terms.breakElephantEye.desc}(${terms.desc})';
            } else {
              return Terms.breakElephantEye;
            }
          }
        }
      }
      break;
    case 3:
      // 3S2*0S5
      if (s5 == 0) return Terms.dot;
      // 3S2*1S5
      if (s5 == 1) {
        if (isOneLine(descCoordinates!)) {
          if (isOneOne(descCoordinates)) {
            return Terms.dotOneOne;
          } else {
            return Terms.sharp;
          }
        } else {
          return Terms.thrustPeep;
        }
      }
      break;
    case 4:
      // 4S2*0S5
      if (s5 == 0) return Terms.dot;
      break;
  }
  return Terms.none;
}
